﻿/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../global/head.h"
#include "../macro/head.h"
#include "aio_epoll_notify.h"
#include "aio_thread.h"
#include "aio_impl.h"

/////////////////////////////////////////////////////////////////////////////////////////
// 
namespace xos_aio
{
    aio_epoll_notify::aio_epoll_notify( aio_impl * pAioImpl ) : m_pAioImpl( pAioImpl )
    {
        memset( m_nPipe, -1, sizeof( m_nPipe ) );
    }

    aio_epoll_notify::~aio_epoll_notify()
    {
    }

    ////////////////////////////////////////////////////////////////////////////////////
    // 

    int aio_epoll_notify::init()
    {
        int nRet = 0;

        int hRead = 0;
        int opts = 0;

        if( 0 == nRet )
        {
            int ret = pipe( m_nPipe );

            if( ret < 0 )
            {
                memset( m_nPipe, -1, sizeof( m_nPipe ) );
                nRet = 1;
            }
            else
            {
                hRead = m_nPipe[0];
            }
        }

        if( 0 == nRet )
        {
            opts = fcntl( hRead, F_GETFL );

            if( opts < 0 )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            opts = opts | O_NONBLOCK;
            nRet = fcntl( hRead, F_SETFL, opts );
        }

        if( 0 == nRet )
        {
            struct epoll_event ev;
            ev.events = EPOLLIN;
            ev.data.ptr = this;
            if( epoll_ctl( m_pAioImpl->m_hEpoll, EPOLL_CTL_ADD, hRead, &ev ) < 0 )
            {
                nRet = 1;
            }
        }

        return nRet;
    }

    int aio_epoll_notify::term()
    {
        int nRet = 0;

        if( -1 != m_nPipe[0] )
        {
            epoll_ctl( m_pAioImpl->m_hEpoll, EPOLL_CTL_DEL, m_nPipe[0], 0 );
        }

        for( int i = 0; i < 2; ++i )
        {
            close( m_nPipe[i] );
            m_nPipe[i] = 0;
        }

        return nRet;
    }

    int aio_epoll_notify::reset()
    {
        int nRet = 0;

        int hRead = m_nPipe[0];
        char buf[8192];
        ::read( hRead, buf, sizeof( buf ) );

        return nRet;
    }

    //////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // notify epoll_wait to ret for user command.
    // 
    int aio_epoll_notify::set_event()
    {
        int nRet = 0;
        ::write( m_nPipe[1], "1", 1 );
        return nRet;
    }

    // 
    // process user request 
    // 
    int aio_epoll_notify::notify( xos_box::i_msg *& lpMsg )
    {
        using namespace std;
        int nRet = 0;

        aio_data::LIST & data_list = m_pAioImpl->m_request_list;
		aio_data * p = aio_data::get_item_from_pool( true );
        p->init();
        p->m_pMsg = lpMsg;
        lpMsg = 0;

        data_list.lock();
        data_list.push_back( p );
        data_list.un_lock();
        set_event();

        return nRet;
    }

} // xos_aio
